package com.smart.community.region.controller;

import com.smart.community.commons.annotation.ApiLog;
import com.smart.community.commons.enums.ApiLogOperationType;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.result.Result;
import com.smart.community.region.dto.ShopRentRecordDTO;
import com.smart.community.region.dto.PaymentInfoDTO;
import com.smart.community.region.service.IShopRentRecordService;
import com.smart.community.region.vo.ShopRentRecordVO;
import com.smart.community.region.vo.ShopRentStatisticsVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 店铺租金管理控制器
 * 
 * @author Wu.Liang
 * @version 1.0.0
 * @since 2025-01-30
 */
@Slf4j
@RestController
@RequestMapping("/region/shop-rents")
@Tag(name = "店铺租金管理", description = "店铺租金管理相关接口")
public class ShopRentController {
    
    @Autowired
    private IShopRentRecordService shopRentRecordService;
    
    /**
     * 分页查询租金记录
     */
    @GetMapping("/page")
    @Operation(summary = "分页查询租金记录", description = "分页查询租金记录")
    public Result<PageResult<ShopRentRecordVO>> getRentRecordPage(
            @Parameter(description = "当前页") @RequestParam(value = "current", defaultValue = "1") Integer current,
            @Parameter(description = "每页大小") @RequestParam(value = "size", defaultValue = "10") Integer size,
            @Parameter(description = "店铺ID") @RequestParam(required = false) Long shopId,
            @Parameter(description = "店铺业主ID") @RequestParam(required = false) Long ownerId,
            @Parameter(description = "支付状态") @RequestParam(required = false) Integer paymentStatus,
            @Parameter(description = "租金期间") @RequestParam(required = false) String rentPeriod,
            @Parameter(description = "租金月份") @RequestParam(required = false) String rentMonth,
            @Parameter(description = "开始日期") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) throws Exception {
        
        // 参数校验
        if (current == null || current < 1) {
            return Result.fail("页码必须大于0");
        }
        if (size == null || size < 1 || size > 100) {
            return Result.fail("每页大小必须在1-100之间");
        }
        
        // 业务逻辑
        PageResult<ShopRentRecordVO> result = shopRentRecordService.getRentRecordPage(current, size, shopId, ownerId, paymentStatus, rentPeriod, rentMonth, startDate, endDate);
        return Result.success("查询成功", result);
    }
    
    /**
     * 根据ID获取租金记录详情
     */
    @GetMapping("/{id}")
    @Operation(summary = "根据ID获取租金记录详情", description = "根据ID获取租金记录详情")
    public Result<ShopRentRecordVO> getRentRecordById(@Parameter(description = "记录ID") @PathVariable Long id) throws Exception {
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("记录ID必须大于0");
        }
        
        // 业务逻辑
        ShopRentRecordVO result = shopRentRecordService.getRentRecordById(id);
        if (result == null) {
            return Result.fail("租金记录不存在");
        }
        
        return Result.success("查询成功", result);
    }
    
    /**
     * 创建租金记录
     */
    @ApiLog(
        logTitle = "创建租金记录",
        logType = 2,
        moduleName = "区域管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping
    @Operation(summary = "创建租金记录", description = "创建新租金记录，支持单条记录和批量生成月度租金记录")
    public Result<Object> createRentRecord(@Parameter(description = "租金记录信息") @RequestBody @Valid ShopRentRecordDTO rentRecordDTO) throws Exception {
        // 参数校验
        if (rentRecordDTO == null) {
            return Result.fail("租金记录信息不能为空");
        }
        
        // 业务参数校验
        validateRentRecordDTO(rentRecordDTO);
        
        // 判断是否为批量生成月度租金记录
        if (isBatchMonthlyRentRecord(rentRecordDTO)) {
            // 批量生成月度租金记录
            return handleBatchMonthlyRentRecord(rentRecordDTO);
        } else {
            // 单条记录创建
            Long recordId = shopRentRecordService.createRentRecord(rentRecordDTO);
            return Result.success("租金记录创建成功", recordId);
        }
    }
    
    /**
     * 更新租金记录
     */
    @ApiLog(
        logTitle = "更新租金记录",
        logType = 2,
        moduleName = "区域管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/{id}")
    @Operation(summary = "更新租金记录", description = "更新租金记录信息")
    public Result<Boolean> updateRentRecord(
            @Parameter(description = "记录ID") @PathVariable Long id,
            @Parameter(description = "租金记录信息") @RequestBody @Valid ShopRentRecordDTO rentRecordDTO) throws Exception {
        
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("记录ID必须大于0");
        }
        if (rentRecordDTO == null) {
            return Result.fail("租金记录信息不能为空");
        }
        
        // 业务参数校验
        validateRentRecordDTO(rentRecordDTO);
        
        // 业务逻辑
        rentRecordDTO.setId(id);
        Boolean result = shopRentRecordService.updateRentRecord(rentRecordDTO);
        return Result.success("租金记录更新成功", result);
    }
    
    /**
     * 删除租金记录
     */
    @ApiLog(
        logTitle = "删除租金记录",
        logType = 2,
        moduleName = "区域管理",
        operationType = ApiLogOperationType.DELETE
    )
    @DeleteMapping("/{id}")
    @Operation(summary = "删除租金记录", description = "删除租金记录")
    public Result<Boolean> deleteRentRecord(@Parameter(description = "记录ID") @PathVariable Long id) throws Exception {
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("记录ID必须大于0");
        }
        
        // 业务逻辑
        Boolean result = shopRentRecordService.deleteRentRecord(id);
        return Result.success("租金记录删除成功", result);
    }
    
    /**
     * 支付租金
     */
    @ApiLog(
        logTitle = "支付租金",
        logType = 2,
        moduleName = "区域管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PostMapping("/{recordId}/pay")
    @Operation(summary = "支付租金", description = "支付租金")
    public Result<Boolean> payRent(
            @Parameter(description = "记录ID") @PathVariable Long recordId,
            @Parameter(description = "支付信息") @RequestBody @Valid PaymentInfoDTO paymentInfo) throws Exception {
        
        // 参数校验
        if (recordId == null || recordId <= 0) {
            return Result.fail("记录ID必须大于0");
        }
        if (paymentInfo == null) {
            return Result.fail("支付信息不能为空");
        }
        
        // 业务参数校验
        validatePaymentInfoDTO(paymentInfo);
        
        // 业务逻辑
        Boolean result = shopRentRecordService.payRent(recordId, paymentInfo);
        return Result.success("租金支付成功", result);
    }
    
    /**
     * 获取租金统计
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取租金统计", description = "获取租金统计信息")
    public Result<ShopRentStatisticsVO> getRentStatistics(
            @Parameter(description = "店铺ID") @RequestParam(required = false) Long shopId,
            @Parameter(description = "开始日期") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) throws Exception {
        
        // 业务逻辑
        ShopRentStatisticsVO result = shopRentRecordService.getRentStatistics(shopId, startDate, endDate);
        return Result.success("查询成功", result);
    }
    
    /**
     * 根据店铺ID获取租金记录列表
     */
    @GetMapping("/shop/{shopId}")
    @Operation(summary = "根据店铺ID获取租金记录列表", description = "根据店铺ID获取租金记录列表")
    public Result<List<ShopRentRecordVO>> getRentRecordsByShopId(@Parameter(description = "店铺ID") @PathVariable Long shopId) throws Exception {
        // 参数校验
        if (shopId == null || shopId <= 0) {
            return Result.fail("店铺ID必须大于0");
        }
        
        // 业务逻辑
        List<ShopRentRecordVO> result = shopRentRecordService.getRentRecordsByShopId(shopId);
        return Result.success("查询成功", result);
    }
    
    
    /**
     * 根据支付状态获取租金记录列表
     */
    @GetMapping("/status/{paymentStatus}")
    @Operation(summary = "根据支付状态获取租金记录列表", description = "根据支付状态获取租金记录列表")
    public Result<List<ShopRentRecordVO>> getRentRecordsByPaymentStatus(@Parameter(description = "支付状态") @PathVariable Integer paymentStatus) throws Exception {
        // 参数校验
        if (paymentStatus == null || paymentStatus < 0 || paymentStatus > 2) {
            return Result.fail("支付状态参数不正确");
        }
        
        // 业务逻辑
        List<ShopRentRecordVO> result = shopRentRecordService.getRentRecordsByPaymentStatus(paymentStatus);
        return Result.success("查询成功", result);
    }
    
    /**
     * 判断是否为批量生成月度租金记录
     */
    private boolean isBatchMonthlyRentRecord(ShopRentRecordDTO rentRecordDTO) {
        // 判断条件：
        // 1. 是月度租金 (isMonthlyRent = 1)
        // 2. 有租赁开始和结束日期
        // 3. 租赁期间跨越多个月份
        boolean isMonthlyRent = rentRecordDTO.getIsMonthlyRent() != null && 
                               rentRecordDTO.getIsMonthlyRent() == 1;
        boolean hasLeaseDates = rentRecordDTO.getLeaseStartDate() != null &&
                               rentRecordDTO.getLeaseEndDate() != null;
        boolean isMultiMonth = hasLeaseDates && 
                              isMultiMonthPeriod(rentRecordDTO.getLeaseStartDate(), rentRecordDTO.getLeaseEndDate());
        
        log.info("批量生成判断: isMonthlyRent={}, hasLeaseDates={}, isMultiMonth={}", 
            isMonthlyRent, hasLeaseDates, isMultiMonth);
        
        return isMonthlyRent && hasLeaseDates && isMultiMonth;
    }
    
    /**
     * 判断租赁期间是否跨越多个月份
     */
    private boolean isMultiMonthPeriod(LocalDate startDate, LocalDate endDate) {
        if (startDate == null || endDate == null) {
            log.warn("租赁期间参数为空: startDate={}, endDate={}", startDate, endDate);
            return false;
        }
        
        if (startDate.isAfter(endDate)) {
            log.warn("租赁开始日期晚于结束日期: startDate={}, endDate={}", startDate, endDate);
            return false;
        }
        
        // 计算月份差
        int yearDiff = endDate.getYear() - startDate.getYear();
        int monthDiff = endDate.getMonthValue() - startDate.getMonthValue();
        int totalMonthDiff = yearDiff * 12 + monthDiff;
        
        log.info("月份差计算: startDate={}, endDate={}, totalMonthDiff={}", 
            startDate, endDate, totalMonthDiff);
        
        // 如果跨越多个月份，则认为是批量生成
        return totalMonthDiff > 0;
    }
    
    /**
     * 处理批量生成月度租金记录
     */
    private Result<Object> handleBatchMonthlyRentRecord(ShopRentRecordDTO rentRecordDTO) throws Exception {
        try {
            log.info("开始处理批量生成月度租金记录: shopId={}, 租赁期间={} 到 {}", 
                rentRecordDTO.getShopId(), rentRecordDTO.getLeaseStartDate(), rentRecordDTO.getLeaseEndDate());
            
            // 生成月度租金记录列表
            List<ShopRentRecordDTO> monthlyRecords = generateMonthlyRentRecords(rentRecordDTO);
            
            if (monthlyRecords.isEmpty()) {
                log.warn("无法生成月度租金记录，请检查租赁期间设置");
                return Result.fail("无法生成月度租金记录，请检查租赁期间设置");
            }
            
            log.info("准备创建 {} 条月度租金记录", monthlyRecords.size());
            
            // 批量创建租金记录
            int successCount = 0;
            int failCount = 0;
            List<Long> createdRecordIds = new ArrayList<>();
            
            for (int i = 0; i < monthlyRecords.size(); i++) {
                ShopRentRecordDTO record = monthlyRecords.get(i);
                try {
                    log.info("创建第 {} 条月度租金记录: 月份={}, 期间={} 到 {}", 
                        i + 1, record.getRentMonth(), record.getRentStartDate(), record.getRentEndDate());
                    
                    Long recordId = shopRentRecordService.createRentRecord(record);
                    if (recordId != null && recordId > 0) {
                        successCount++;
                        createdRecordIds.add(recordId);
                        log.info("第 {} 条记录创建成功，ID: {}", i + 1, recordId);
                    } else {
                        failCount++;
                        log.error("第 {} 条记录创建失败，返回ID为空", i + 1);
                    }
                } catch (Exception e) {
                    log.error("第 {} 条记录创建异常: {}", i + 1, e.getMessage(), e);
                    failCount++;
                }
            }
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("totalCount", monthlyRecords.size());
            result.put("successCount", successCount);
            result.put("failCount", failCount);
            result.put("createdRecordIds", createdRecordIds);
            
            log.info("批量创建完成: 总数={}, 成功={}, 失败={}", 
                monthlyRecords.size(), successCount, failCount);
            
            if (successCount > 0) {
                String message = String.format("批量创建月度租金记录成功！成功创建 %d 条记录", successCount);
                if (failCount > 0) {
                    message += String.format("，失败 %d 条", failCount);
                }
                return Result.success(message, result);
            } else {
                return Result.fail("批量创建月度租金记录失败，请检查数据设置");
            }
            
        } catch (Exception e) {
            log.error("批量生成月度租金记录异常: {}", e.getMessage(), e);
            return Result.fail("批量生成月度租金记录失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成月度租金记录列表
     */
    private List<ShopRentRecordDTO> generateMonthlyRentRecords(ShopRentRecordDTO rentRecordDTO) {
        List<ShopRentRecordDTO> records = new ArrayList<>();
        
        LocalDate startDate = rentRecordDTO.getLeaseStartDate();
        LocalDate endDate = rentRecordDTO.getLeaseEndDate();
        
        if (startDate == null || endDate == null || startDate.isAfter(endDate)) {
            log.warn("租赁期间参数无效: startDate={}, endDate={}", startDate, endDate);
            return records;
        }
        
        log.info("开始生成月度租金记录: 租赁期间从 {} 到 {}", startDate, endDate);
        
        // 从租赁开始日期的月份开始，逐月生成记录
        LocalDate currentMonth = startDate.withDayOfMonth(1); // 开始月份的第一天
        LocalDate endMonth = endDate.withDayOfMonth(1); // 结束月份的第一天
        
        while (!currentMonth.isAfter(endMonth)) {
            // 计算当前月份的第一天和最后一天
            LocalDate monthStart = currentMonth.withDayOfMonth(1);
            LocalDate monthEnd = currentMonth.withDayOfMonth(currentMonth.lengthOfMonth());
            
            // 调整开始日期：如果是第一个月，使用实际的租赁开始日期
            if (currentMonth.equals(startDate.withDayOfMonth(1))) {
                monthStart = startDate;
            }
            
            // 调整结束日期：如果是最后一个月，使用实际的租赁结束日期
            if (currentMonth.equals(endDate.withDayOfMonth(1))) {
                monthEnd = endDate;
            }
            
            // 创建月度租金记录
            ShopRentRecordDTO monthlyRecord = new ShopRentRecordDTO();
            monthlyRecord.setShopId(rentRecordDTO.getShopId());
            monthlyRecord.setRentAmount(rentRecordDTO.getRentAmount());
            monthlyRecord.setRentMonth(String.format("%04d-%02d", currentMonth.getYear(), currentMonth.getMonthValue()));
            monthlyRecord.setIsMonthlyRent(1);
            monthlyRecord.setLeaseStartDate(monthStart);
            monthlyRecord.setLeaseEndDate(monthEnd);
            monthlyRecord.setRentPeriod(String.format("%04d-%02d", currentMonth.getYear(), currentMonth.getMonthValue()));
            monthlyRecord.setRentStartDate(monthStart);
            monthlyRecord.setRentEndDate(monthEnd);
            monthlyRecord.setPaymentStatus(0); // 默认未支付
            monthlyRecord.setPaymentMethod(rentRecordDTO.getPaymentMethod());
            monthlyRecord.setInvoiceNumber(rentRecordDTO.getInvoiceNumber());
            monthlyRecord.setRemark(String.format("月度租金 - %04d年%02d月", currentMonth.getYear(), currentMonth.getMonthValue()));
            
            log.info("生成月度租金记录: 月份={}, 期间={} 到 {}", 
                monthlyRecord.getRentMonth(), monthStart, monthEnd);
            
            records.add(monthlyRecord);
            
            // 移动到下个月
            currentMonth = currentMonth.plusMonths(1);
        }
        
        log.info("月度租金记录生成完成，共生成 {} 条记录", records.size());
        return records;
    }
    
    /**
     * 租金记录DTO业务规则验证
     */
    private void validateRentRecordDTO(ShopRentRecordDTO rentRecordDTO) {
        // 店铺ID校验
        if (rentRecordDTO.getShopId() == null || rentRecordDTO.getShopId() <= 0) {
            throw new IllegalArgumentException("店铺ID必须大于0");
        }
        
        // 租金金额校验
        if (rentRecordDTO.getRentAmount() == null || rentRecordDTO.getRentAmount().doubleValue() <= 0) {
            throw new IllegalArgumentException("租金金额必须大于0");
        }
        
        // 是否月度租金校验
        if (rentRecordDTO.getIsMonthlyRent() == null) {
            throw new IllegalArgumentException("是否月度租金不能为空");
        }
        
        // 如果是月度租金，需要验证租赁期间
        if (rentRecordDTO.getIsMonthlyRent() == 1) {
            // 租赁开始日期校验
            if (rentRecordDTO.getLeaseStartDate() == null) {
                throw new IllegalArgumentException("月度租金租赁开始日期不能为空");
            }
            
            // 租赁结束日期校验
            if (rentRecordDTO.getLeaseEndDate() == null) {
                throw new IllegalArgumentException("月度租金租赁结束日期不能为空");
            }
            
            // 租赁期间逻辑校验
            if (rentRecordDTO.getLeaseStartDate().isAfter(rentRecordDTO.getLeaseEndDate())) {
                throw new IllegalArgumentException("租赁开始日期不能晚于结束日期");
            }
            
            // 租赁期间长度校验（不能超过5年）
            long daysBetween = java.time.temporal.ChronoUnit.DAYS.between(
                rentRecordDTO.getLeaseStartDate(), 
                rentRecordDTO.getLeaseEndDate()
            );
            if (daysBetween > 1825) { // 5年 = 1825天
                throw new IllegalArgumentException("租赁期间不能超过5年");
            }
        } else {
            // 非月度租金，验证单条记录字段
            // 租金期间校验
            if (rentRecordDTO.getRentPeriod() == null || rentRecordDTO.getRentPeriod().trim().isEmpty()) {
                throw new IllegalArgumentException("租金期间不能为空");
            }
            
            // 租金开始日期校验
            if (rentRecordDTO.getRentStartDate() == null) {
                throw new IllegalArgumentException("租金开始日期不能为空");
            }
            
            // 租金结束日期校验
            if (rentRecordDTO.getRentEndDate() == null) {
                throw new IllegalArgumentException("租金结束日期不能为空");
            }
            
            // 日期逻辑校验
            if (rentRecordDTO.getRentStartDate().isAfter(rentRecordDTO.getRentEndDate())) {
                throw new IllegalArgumentException("租金开始日期不能晚于结束日期");
            }
        }
        
        // 支付状态校验
        if (rentRecordDTO.getPaymentStatus() != null && 
            (rentRecordDTO.getPaymentStatus() < 0 || rentRecordDTO.getPaymentStatus() > 2)) {
            throw new IllegalArgumentException("支付状态参数不正确，应为0-2");
        }
        
        // 支付方式校验
        if (rentRecordDTO.getPaymentMethod() != null && !rentRecordDTO.getPaymentMethod().trim().isEmpty()) {
            String[] validMethods = {"CASH", "BANK_TRANSFER", "ALIPAY", "WECHAT_PAY", "OTHER"};
            boolean isValidMethod = false;
            for (String method : validMethods) {
                if (method.equals(rentRecordDTO.getPaymentMethod())) {
                    isValidMethod = true;
                    break;
                }
            }
            if (!isValidMethod) {
                throw new IllegalArgumentException("支付方式不正确，支持的方式：CASH、BANK_TRANSFER、ALIPAY、WECHAT_PAY、OTHER");
            }
        }
    }
    
    /**
     * 支付信息DTO业务规则验证
     */
    private void validatePaymentInfoDTO(PaymentInfoDTO paymentInfo) {
        // 支付方式校验
        if (paymentInfo.getPaymentMethod() == null || paymentInfo.getPaymentMethod().trim().isEmpty()) {
            throw new IllegalArgumentException("支付方式不能为空");
        }
        
        // 支付金额校验
        if (paymentInfo.getPaymentAmount() == null || paymentInfo.getPaymentAmount().doubleValue() <= 0) {
            throw new IllegalArgumentException("支付金额必须大于0");
        }
        
        // 支付方式枚举校验
        String[] validMethods = {"CASH", "BANK_TRANSFER", "ALIPAY", "WECHAT_PAY", "OTHER"};
        boolean isValidMethod = false;
        for (String method : validMethods) {
            if (method.equals(paymentInfo.getPaymentMethod())) {
                isValidMethod = true;
                break;
            }
        }
        if (!isValidMethod) {
            throw new IllegalArgumentException("支付方式不正确，支持的方式：CASH、BANK_TRANSFER、ALIPAY、WECHAT_PAY、OTHER");
        }
    }
}
